package me.stone.stanimeclient.core.ui.item

import androidx.databinding.BindingAdapter
import androidx.paging.LoadState
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.cachedIn
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import me.stone.stanimeclient.core.common.di.ApplicationScope
import me.stone.stanimeclient.core.model.FanSimpleItem
import me.stone.stanimeclient.core.ui.adapters.FanSimpleListAdapter
import me.stone.stanimeclient.core.ui.adapters.listener.OnItemClickListener
import javax.inject.Inject

@Suppress("UNUSED")
object FanOtherBindingAdapters {

    @JvmStatic
    @BindingAdapter("fanSimpleAdapter")
    fun setFanSimpleAdapter(recyclerView: RecyclerView, adapter: FanSimpleListAdapter) {
        recyclerView.adapter = adapter
    }

}

class FanOtherBindingHelper @Inject constructor(
    @ApplicationScope private val coroutineScope: CoroutineScope,
) {
    private val _otherFanItem = MutableSharedFlow<FanSimpleItem>()

    val otherFanItem: SharedFlow<FanSimpleItem> = _otherFanItem

    val adapter = FanSimpleListAdapter().apply {
        enableDynamicHeight = true
        setOnItemClickListener {
            coroutineScope.launch { _otherFanItem.emit(it) }
        }
    }

    fun updateAdapterMode(cover: Boolean) {
        if (cover) {
            adapter.toGridStyle()
        } else {
            adapter.toLineStyle()
        }
    }

    private var refreshing = false

    init {
        coroutineScope.launch {
            adapter.loadStateFlow.collectLatest {
                if (it.refresh is LoadState.Loading) {
                    refreshing = true
                } else if (refreshing) {
                    refreshing = false
                    adapter.updateRecyclerDynamicHeight()
                }
            }
        }
    }

    private val _labelTitle = MutableStateFlow(0)

    val labelTitle: StateFlow<Int> = _labelTitle

    fun updateLabelTitle(resId: Int) {
        coroutineScope.launch {
            _labelTitle.emit(resId)
        }
    }

    private val _dataFlow = MutableStateFlow<List<FanSimpleItem>>(emptyList())

    @Suppress("UNUSED")
    @OptIn(ExperimentalCoroutinesApi::class)
    val dataFlow = _dataFlow
        .filter { it.isNotEmpty() }
        .flatMapLatest {
            Pager(PagingConfig(0)) {
                DataPagingSource(it)
            }.flow
        }
        .cachedIn(coroutineScope)
        .onEach { adapter.submitData(it) }
        .shareIn(coroutineScope, SharingStarted.Eagerly)

    val hasFanSimpleList: StateFlow<Boolean> = _dataFlow
        .map { it.isNotEmpty() }
        .stateIn(coroutineScope, SharingStarted.Eagerly, false)

    fun updateData(data: List<FanSimpleItem>) {
        coroutineScope.launch {
            _dataFlow.emit(data)
        }
    }

    private class DataPagingSource(
        val data: List<FanSimpleItem>
    ): PagingSource<Unit, FanSimpleItem>() {

        override fun getRefreshKey(state: PagingState<Unit, FanSimpleItem>): Unit? {
            return null
        }

        override suspend fun load(params: LoadParams<Unit>): LoadResult<Unit, FanSimpleItem> {
            return LoadResult.Page(data = data, nextKey = null, prevKey = null)
        }

    }

}